package com.interview.rtc.aigc.config;

import com.fasterxml.jackson.databind.ObjectMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;
import org.springframework.web.util.ContentCachingRequestWrapper;
import org.springframework.web.util.ContentCachingResponseWrapper;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;

/**
 * 请求和响应日志记录过滤器
 */
@Component
public class RequestLoggingFilter extends OncePerRequestFilter {

    private static final Logger logger = LoggerFactory.getLogger(RequestLoggingFilter.class);
    private static final ObjectMapper objectMapper = new ObjectMapper();

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
            throws ServletException, IOException {
        // 包装请求和响应，以便多次读取内容
        ContentCachingRequestWrapper requestWrapper = new ContentCachingRequestWrapper(request);
        ContentCachingResponseWrapper responseWrapper = new ContentCachingResponseWrapper(response);

        long startTime = System.currentTimeMillis();

        try {
            // 继续过滤链处理
            filterChain.doFilter(requestWrapper, responseWrapper);
        } finally {
            // 记录请求信息
            String requestURI = requestWrapper.getRequestURI();
            String method = requestWrapper.getMethod();
            String remoteAddr = requestWrapper.getRemoteAddr();

            // 获取请求参数
            Map<String, String> requestParams = getRequestParameters(requestWrapper);

            // 获取请求体
            String requestBody = "";
            byte[] requestBodyBytes = requestWrapper.getContentAsByteArray();
            if (requestBodyBytes.length > 0) {
                requestBody = new String(requestBodyBytes);
            }

            // 获取响应体
            String responseBody = "";
            byte[] responseBodyBytes = responseWrapper.getContentAsByteArray();
            if (responseBodyBytes.length > 0) {
                responseBody = new String(responseBodyBytes);
            }

            // 计算处理时间
            long duration = System.currentTimeMillis() - startTime;

            // 获取响应状态码
            int statusCode = responseWrapper.getStatus();

            // 跳过OPTIONS请求的日志记录
            if ("OPTIONS".equalsIgnoreCase(method)) {
                // 必须复制响应体内容，否则客户端收不到响应
                responseWrapper.copyBodyToResponse();
                return;
            }

            // 构建单条日志信息，使用换行和缩进提高可读性
            StringBuilder logMessage = new StringBuilder();
            logMessage.append(String.format("请求/响应详情: %s %s\n", method, requestURI));
            logMessage.append(String.format("    IP地址: %s\n", remoteAddr));
            logMessage.append(String.format("    状态码: %d\n", statusCode));
            logMessage.append(String.format("    耗时: %dms\n", duration));

            // 根据需要添加详细信息
            // 添加请求参数
            try {
                logMessage.append(String.format("    请求参数: %s\n", objectMapper.writeValueAsString(requestParams)));
            } catch (Exception e) {
                logMessage.append("    请求参数: [序列化失败]\n");
            }

            // 添加请求体
            if (!requestBody.isEmpty()) {
                logMessage.append(String.format("    请求体: %s\n", requestBody));
            }

            // 添加响应体
            if (!responseBody.isEmpty()) {
                logMessage.append(String.format("    响应体: %s\n", responseBody));
            }

            // 根据状态码决定日志级别
            if (statusCode == 200) {
                logger.info(logMessage.toString());
            } else {
                logger.error(logMessage.toString());
            }

            // 必须复制响应体内容，否则客户端收不到响应
            responseWrapper.copyBodyToResponse();
        }
    }

    /**
     * 获取所有请求参数
     */
    private Map<String, String> getRequestParameters(HttpServletRequest request) {
        Map<String, String> parameters = new HashMap<>();
        Enumeration<String> paramNames = request.getParameterNames();

        while (paramNames.hasMoreElements()) {
            String paramName = paramNames.nextElement();
            String paramValue = request.getParameter(paramName);
            parameters.put(paramName, paramValue);
        }

        // 添加请求头信息
        Enumeration<String> headerNames = request.getHeaderNames();
        Map<String, String> headers = new HashMap<>();
        while (headerNames.hasMoreElements()) {
            String headerName = headerNames.nextElement();
            // 排除敏感的认证信息
            if (!"authorization".equalsIgnoreCase(headerName)) {
                headers.put(headerName, request.getHeader(headerName));
            } else {
                headers.put(headerName, "******");
            }
        }

        parameters.put("headers", headers.toString());
        return parameters;
    }
}
